package eu.briano.suirvellancecamera.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.android.AndroidAuthSession;
import eu.briano.suirvellancecamera.Log;
import eu.briano.suirvellancecamera.R;
import eu.briano.suirvellancecamera.Utils;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Binder;
import android.os.IBinder;

import android.widget.Toast;

public class Background extends Service {
	private NotificationManager mNM;
	private int NOTIFICATION = R.string.background_service_started;

	private DropboxAPI<AndroidAuthSession> mDBApi;

	public class LocalBinder extends Binder {
		public Background getService() {
			return Background.this;
		}
	}

	Timer timer = null;
	protected boolean taskRunning = false;

	@Override
	public void onCreate() {
		mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		showNotification();
		Log.i(Utils.logName, "Service onCreate");
		timer = new Timer();
		Date startDate = new Date();

		mDBApi = Utils.dropBoxConnect(this);

		TimerTask task = new TimerTask() {
			@Override
			public void run() {
				if (taskRunning) {
					Log.i(Utils.logName, "DropBox task skipped " + this.toString());
					return;
				}
				taskRunning = true;

				try {
					Log.i(Utils.logName, "DropBox task start " + this.toString());
					convertImages();
					sendImages();
					Log.i(Utils.logName, "DropBox task end " + this.toString());
				} catch (Throwable e) {
					Log.e(Utils.logName, "DropBox error on spooling files ", e);
				}
				taskRunning = false;
			}

		};

		timer.scheduleAtFixedRate(task, startDate,
				Utils.backgroundPollingPeriod);

	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(Utils.logName, "Service Received start id " + startId + ": "
				+ intent);
		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		mNM.cancel(NOTIFICATION);
		Toast.makeText(this, R.string.background_service_stopped,
				Toast.LENGTH_SHORT).show();
		if (timer != null) {
			timer.cancel();
			timer = null;
		}
		Log.i(Utils.logName, "Service onDestroy");
	}

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(Utils.logName, "Service binded");
		return mBinder;
	}

	private void convertImages() {
		File imageDir = new File(Utils.getSendFileBasePath());
		if (imageDir.isDirectory()) {
			File[] files = imageDir.listFiles();
			Arrays.sort(files);
			for (File file : files) {
				if (!file.getName().contains("-")
						|| file.getName().contains("processed")
						|| file.getName().contains("map")
						|| file.getName().contains("txt"))
					continue;
				long timestamp = Utils.parseFormattedTimestamp(file.getName());
				if (timestamp == 0)
					continue;
				Calendar now = Calendar.getInstance();
				now.setTimeInMillis(timestamp);
				
				String mapFile = file.getAbsolutePath() + ".map";
				try {
					Bitmap immutableBitmap = BitmapFactory.decodeFile(file
							.getAbsolutePath());
					if (immutableBitmap != null) {
						Bitmap mutableBitmap = immutableBitmap.copy(
								Bitmap.Config.ARGB_8888, true);
						immutableBitmap.recycle();
						immutableBitmap = null;
						Canvas c = new Canvas(mutableBitmap);

						String text = now.getTime().toGMTString();
						Paint p = new Paint();

						p.setColor(Color.BLACK);
						p.setAlpha(100);
						c.drawRoundRect(
								new RectF(0, 0, mutableBitmap.getWidth(), 30),
								0f, 0f, p);
						p.setColor(Color.WHITE);
						p.setTextSize(17);
						p.setAntiAlias(true);
						p.setTypeface(Typeface.SERIF);
						c.drawText(text, 10, 23, p);

						OutputStream os = new FileOutputStream(file.getAbsolutePath()+".processed");
						mutableBitmap.compress(Bitmap.CompressFormat.JPEG,
								Utils.imageQuality, os);
						os.flush();
						os.close();

						Bitmap map = BitmapFactory.decodeFile(mapFile);
						if (map != null) {
							p.setColor(Color.WHITE);
							p.setAlpha(128);

							c.drawBitmap(map, new Rect(0, 0, Utils.ipSize,
									Utils.ipSize),
									new Rect(0, 0, mutableBitmap.getWidth(),
											mutableBitmap.getHeight()), p);
							
							
							try {
								text = Utils.readFile(file.getAbsolutePath() + ".txt");
								c.drawText(text, 10, 44, p);
								new File  (file.getAbsolutePath() + ".txt").delete();
							} catch (Exception e) {
								Log.w(Utils.logName,"DropBox cannot print info ",e);
							}
							
							
							
							os = new FileOutputStream(mapFile+".processed");
							mutableBitmap.compress(Bitmap.CompressFormat.JPEG,
									Utils.imageQuality, os);

						}
						map.recycle();
						map = null;
						mutableBitmap.recycle();
						mutableBitmap = null;
						
						
						file.delete();
						new File(mapFile).delete();
						
						Log.v(Utils.logName, "DropBox file processed "+file.getName());
						
					}
				} catch (Throwable e) {
					Log.e(Utils.logName, "DropBox draw error", e);
				}

			}
		}

	}

	private void sendImages() {
		File imageDir = new File(Utils.getSendFileBasePath());
		if (imageDir.isDirectory()) {
			File[] files = imageDir.listFiles();
			Arrays.sort(files);
			for (File file : files) {
				if (   !file.getName().contains("-")
					|| !file.getName().contains("processed")
				   )
					continue;

				long timestamp = Utils.parseFormattedTimestamp(file.getName());

				if (timestamp == 0)
					continue;

				Calendar now = Calendar.getInstance();
				now.setTimeInMillis(timestamp);
				

				if (file.getName().contains("map"))
					dropBoxPutFile(file, "map/", "", now, true);
				else
					dropBoxPutFile(file, "", "", now, true);
			}
		}

	}

	public void reloadDropBoxConf() {
		mDBApi = Utils.dropBoxConnect(this);
	}

	private void dropBoxPutFile(File srcFile, String prefix, String postFix,
			Calendar now, boolean deleteAfter) {
		if (mDBApi != null && mDBApi.getSession().isLinked()) {
			try {
				FileInputStream inputStream = new FileInputStream(srcFile);
				String destFileName = Utils.getDropBoxFileName(now, postFix,
						prefix);
				mDBApi.putFile(destFileName, inputStream, srcFile.length(),
						null, null);

				Log.v(Utils.logName, "DropBox file putted "+ srcFile.getName() + " "  + destFileName);
				srcFile.delete();
			} catch (Throwable e) {
				Log.e(Utils.logName, "DropBox error on put for:", e);
			}
		} else {
			Log.d(Utils.logName, "DropBox not connected");
		}
	}

	private final IBinder mBinder = new LocalBinder();

	private void showNotification() {
		Toast.makeText(this, R.string.background_service_started,
				Toast.LENGTH_SHORT).show();
		/*
		 * Notification notification = new Notification(R.drawable.icon, text,
		 * System.currentTimeMillis());
		 * 
		 * PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new
		 * Intent(this, SuirvellanceCameraActivity.class), 0);
		 * notification.setLatestEventInfo(this,
		 * getText(R.string.background_service_label), text, contentIntent);
		 * 
		 * mNM.notify(NOTIFICATION, notification);
		 */
	}

}
